package com.e3roid.examples;

import java.io.ByteArrayInputStream;

import android.media.AudioFormat;
import android.media.MediaRecorder;
import android.widget.Toast;

import com.e3roid.E3Activity;
import com.e3roid.E3Engine;
import com.e3roid.E3Scene;
import com.e3roid.audio.AudioInputService;
import com.e3roid.audio.AudioInputListener;
import com.e3roid.drawable.sprite.TextSprite;
import com.e3roid.event.SceneUpdateListener;
import com.e3roid.util.Debug;
import com.e3roid.util.EnvironmentInfo;
import com.e3roid.util.FPSListener;

/**
 * Audio input service example. This example requires mic device and cannot run on the emulator.
 */
public class AudioInputExample extends E3Activity implements FPSListener, AudioInputListener, SceneUpdateListener {

	private final static int WIDTH  = 320;
	private final static int HEIGHT = 480;

	private TextSprite label;
	private AudioInputService audioInputService;
	
	private static float wave = 0;
	
	@Override
	public E3Engine onLoadEngine() {
		E3Engine engine = new E3Engine(this, WIDTH, HEIGHT);
		engine.requestFullScreen();
		
		android.os.Process.setThreadPriority(
		          android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
		
		engine.getFPSCounter().addListener(this);
		return engine;
	}

	@Override
	public E3Scene onLoadScene() {
		E3Scene scene = new E3Scene();
		scene.registerUpdateListener(200, this);
				
		label.move((getWidth() - label.getWidth()) / 2, (getHeight() - label.getHeight()) / 2);
		scene.getTopLayer().add(label);
		
		return scene;
	}

	@Override
	public void onLoadResources() {
		label = new TextSprite("WAV: 0.0000", 36, this);
	}
	
	@Override
	public void onUserResumed() {
		if (EnvironmentInfo.isOnEmulator()) {
			Toast.makeText(this, "Audio input is not supported on the emulator.", Toast.LENGTH_LONG).show();
			return;
		}
		
		// Start the audio input service with given parameters.
		if (audioInputService == null) {
			audioInputService = new AudioInputService(
					MediaRecorder.AudioSource.MIC, 8000, 
					AudioFormat.CHANNEL_CONFIGURATION_MONO, 
					AudioFormat.ENCODING_PCM_16BIT, this);
		}
		getEngine().registerService(audioInputService);
	}
	
	@Override
	public void onUserPaused() {
		stopService();
	}

	@Override
	public void onUserDisposed() {
		stopService();
	}

	/**
	 * Stop the audio input service
	 */
	private void stopService() {
		if (audioInputService != null) {
			getEngine().unregisterService(audioInputService);
			audioInputService = null;
		}
	}
	
	@Override
	public void onFPS(float fps, float min, float max) {
		Debug.d(String.format("FPS: %.2f (MIN %.2f / MAX %.2f)", fps, min, max));
	}

	/**
	 * Read audio buffers
	 */
	@Override
	public void onReadAudioInput(AudioInputService service, byte[] buffer) {
		ByteArrayInputStream bin = new ByteArrayInputStream(buffer);
		if (bin.available() > 0) {
			wave = (float)AudioInputService.readAs16bitWave(bin);
		}
	}

	/**
	 * Show the audio wave values
	 */
	@Override
	public void onUpdateScene(E3Scene scene, long elapsedMsec) {
		label.setText(String.format("WAV: %.4f", Math.abs(wave)));
	}
}